package birdsong.filter;

import java.util.HashMap;
import java.util.Map;

import birdsong.comm.ServerComm;
import birdsong.comm.ServerSideMessage;

public class SpamFilter extends ServerCommDecorator{
	
	// timeout: spam alinea b) (milisegundos)
	protected final static double TIMEOUT_TOEQUAL_MESSAGES = 30000;
	// number of messages required to send warning
	protected final static int MAX_EQUAL_MESSAGE_TOWARNING = 2; 
	// number of messages required to disconnect user
	protected final static int MAX_EQUAL_MESSAGE_TODISCONNET = 3; 
	
	protected final static double TIMEOUT_TOEXCESS_MESSAGES = 30000;
	protected final static int MAX_EXCESS_MESSAGE_TOWARNING = 8;
	protected final static int MAX_EXCESS_MESSAGE_TODISCONNECT = 10;
	
	protected final static double TIMEOUT_TOALLOW_CLIENT_DISCONNECTED = 30000;

	protected Map<String, MonitorEqualsMessage> _listMessageEquals;
	protected Map<String, MonitorExcessMessage> _listMessageExcess;
	protected Map<String, Message> _disconnectedClients;
	
	public SpamFilter(ServerComm concreteServer) {
		super(concreteServer);
		this._listMessageEquals = new HashMap<String, MonitorEqualsMessage>();
		this._listMessageExcess = new HashMap<String, MonitorExcessMessage>();
		this._disconnectedClients = new HashMap<String,Message>();
	}

	/**
	 * @return ServerSideMessage
	 */
	@Override
	public ServerSideMessage getNextMessage() {
		ServerSideMessage message = super.getNextMessage();
		String nickname = message.getClientNickname();
		String payload = message.getPayload();
		
		if(_disconnectedClients.containsKey(nickname))
			if(Monitor.inTimeout(_disconnectedClients.get(nickname), TIMEOUT_TOALLOW_CLIENT_DISCONNECTED))
				return this.getNextMessage();
			else _disconnectedClients.remove(nickname);
		
		if(_listMessageEquals.containsKey(nickname)){
			_listMessageEquals.get(nickname).setMessage(payload);
		}else {
			_listMessageEquals.put(nickname, new MonitorEqualsMessage(TIMEOUT_TOEQUAL_MESSAGES,MAX_EQUAL_MESSAGE_TODISCONNET,MAX_EQUAL_MESSAGE_TOWARNING));
			_listMessageEquals.get(nickname).setMessage(payload);
		}
		
		if(_listMessageExcess.containsKey(nickname)){
			_listMessageExcess.get(nickname).setMessage(payload);
		}else {
			_listMessageExcess.put(nickname, new MonitorExcessMessage(TIMEOUT_TOEXCESS_MESSAGES,MAX_EXCESS_MESSAGE_TODISCONNECT,MAX_EXCESS_MESSAGE_TOWARNING));
			_listMessageExcess.get(nickname).setMessage(payload);
		}
		
		if(_listMessageEquals.get(nickname).sendWarning())
			sendBirdsongMessage("TEST",nickname,"Warning: exceed the flow of messages with the same content");
		
		if(_listMessageExcess.get(nickname).sendWarning())
			sendBirdsongMessage("TEST",nickname,"Warning: exceeded the number of messages allowed");
		
		if(_listMessageEquals.get(nickname).disconnectClient()||
				_listMessageExcess.get(nickname).disconnectClient()){
			this.disconnectClient(nickname);
			return this.getNextMessage();
		}
		return message;
	}
	
	

	/**
	 * @param nickname
	 */
	@Override
	public void disconnectClient(String nickname) {
		_listMessageEquals.remove(nickname);
		_listMessageExcess.remove(nickname);
		_disconnectedClients.put(nickname, new Message(""));
		super.disconnectClient(nickname);
	}
	
	/**
	 * @param nickname
	 * @return
	 */
	@Override
	public boolean clientIsConnected(String nickname){
		if(_disconnectedClients.containsKey(nickname))
			if(Monitor.inTimeout(_disconnectedClients.get(nickname), TIMEOUT_TOALLOW_CLIENT_DISCONNECTED))
				return false;
			else _disconnectedClients.remove(nickname);
		return super.clientIsConnected(nickname);
	}

}
